package com.hj.file.util;


import com.itextpdf.text.DocumentException;
import com.itextpdf.text.exceptions.UnsupportedPdfException;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import com.sun.xml.internal.fastinfoset.Encoder;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.BasicURIResolver;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.core.io.ClassPathResource;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.Iterator;
import java.util.Properties;

public class POIUtils {
    public static void mkDirs(String path) {
        File fileDir = new File(path);
        if (!fileDir.exists()) {
            fileDir.mkdirs();
        }
    }

    public static void word2pdf(String filePath, String fileName, String pdfPath) throws ParserConfigurationException, TransformerException, DocumentException, IOException {
        if (fileName.endsWith(".doc")) {
            doc2pdf(filePath, fileName, pdfPath);
        } else {
            docx2pdf(filePath, fileName, pdfPath);
        }
    }

    public static void docx2pdf(String filePath, String fileName, String pdfPath) throws IOException, DocumentException {
        final String imagePath = filePath + File.separator + "imagePath";
        POIUtils.mkDirs(imagePath);
        XWPFDocument document = new XWPFDocument(new FileInputStream(filePath + File.separator + fileName));
        XHTMLOptions options = XHTMLOptions.create();
        //解析 XHTML配置（设置图片存放路径）
        options.setExtractor(new FileImageExtractor(new File(imagePath)));
        options.URIResolver(new BasicURIResolver(imagePath));
        //将XWPFDocument转换成XHTML
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        XHTMLConverter.getInstance().convert(document, baos, options);
        baos.close();
        String content = baos.toString();
        content = htmlFormate(content);
        html2pdf(content, pdfPath);
    }

    /**
     * 使用 itext
     */
    public static void doc2pdf(String filePath, String fileName, String pdfPath) throws IOException, ParserConfigurationException, TransformerException, DocumentException {
        final String imagePath = filePath + File.separator + "imagePath";
        POIUtils.mkDirs(imagePath);
        HWPFDocument hwpfDocument = new HWPFDocument(new FileInputStream(filePath + File.separator + fileName));
        WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
        wordToHtmlConverter.setPicturesManager(new PicturesManager() {
            @Override
            public String savePicture(byte[] bytes, PictureType pictureType, String s, float v, float v1) {
                File file = new File(imagePath + File.separator + s);
                FileOutputStream out = null;
                try {
                    out = new FileOutputStream(file);
                    out.write(bytes);
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return imagePath + File.separator + s;
            }
        });
        wordToHtmlConverter.processDocument(hwpfDocument);
        org.w3c.dom.Document htmlDocument = wordToHtmlConverter.getDocument();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        DOMSource domSource = new DOMSource(htmlDocument);
        StreamResult streamResult = new StreamResult(outputStream);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer serializer = tf.newTransformer();
        Properties properties = new Properties();
        properties.setProperty(OutputKeys.ENCODING, Encoder.UTF_8);
        properties.setProperty(OutputKeys.INDENT, "yes");
        properties.setProperty(OutputKeys.METHOD, "html");
        serializer.setOutputProperties(properties);
        serializer.transform(domSource, streamResult);
        outputStream.close();
        String content = outputStream.toString();
        content = htmlFormate(content);
        html2pdf(content, pdfPath);
    }

    public static String htmlFormate(String content) {
        org.jsoup.nodes.Document doc = Jsoup.parse(content);
        Elements elements = doc.getElementsByTag("img");
        for (Element element : elements) {
            element.text("  ");
        }
        Elements elementMeta = doc.getElementsByTag("meta");
        for (Element element : elementMeta) {
            element.text("  ");
        }
        Elements elementBody = doc.getElementsByTag("body");
        for (Element element : elementBody) {
            element.attr("style", "font-family:SimSun;");
        }
        content = doc.html().replaceAll("&nbsp;", "  ").replaceAll("font-family:.*?;", "font-family:SimSun;")
                .replaceAll("1.25in", "0.25in");
        //.replaceAll("<style[^>]*?>[\\s\\S]*?<\\/style>"," <style>body{ font-family: SimSun;  }</style>");
        return content;
    }

    public static void html2pdf(String content, String outPath) throws IOException, DocumentException {
        ITextRenderer renderer = new ITextRenderer();
        renderer.getSharedContext().setReplacedElementFactory(new Base64ImgReplacedElementFactory());
        renderer.getSharedContext().getTextRenderer().setSmoothingThreshold(0);
        renderer.setDocumentFromString(content);
        ITextFontResolver fontResolver = renderer.getFontResolver();
        ClassPathResource resource = new ClassPathResource("static" + File.separator + "systemFont" + File.separator + "simsun.ttc");
        fontResolver.addFont(resource.getPath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        renderer.setDocumentFromString(content);
        renderer.layout();
        OutputStream out = new FileOutputStream(new File(outPath));
        renderer.createPDF(out);
        out.close();


    }


    public static void readPdfImage(String filePath, String filename) throws IOException {
        //读取pdf文件
        PdfReader reader = new PdfReader(filePath + File.separator + filename);
        //获得pdf文件的页数
        int sumPage = reader.getNumberOfPages();
        //读取pdf文件中的每一页
        for (int i = 1; i <= sumPage; i++) {
            //得到pdf每一页的字典对象
            readPdfImage(reader, i);
        }

    }

    /**
     * itext 读取内容
     */
    public static String readPdfContent(String filePath, String fileName) throws IOException {
        return readPdfContent(new FileInputStream(filePath + File.separator + fileName));
    }

    /**
     * itext 读取内容
     */
    public static String readPdfContent(InputStream inputStream) throws IOException {
        StringBuffer sb = new StringBuffer();
        PdfReader reader = new PdfReader(inputStream);
        int pageNum = reader.getNumberOfPages();
        for (int i = 1; i <= pageNum; i++) {
            String con = PdfTextExtractor.getTextFromPage(reader, i);
            readPdfImage(reader, i);
            sb.append(con);
        }
        inputStream.close();
        reader.close();
        System.out.println(sb.toString());
        return sb.toString();
    }

    /**
     * itext读取图片
     */
    public static void readPdfImage(PdfReader reader, int i) throws IOException {
        String imagePath = "D:\\testWord\\image\\";
        PdfDictionary dictionary = reader.getPageN(i);
        //通过RESOURCES得到对应的字典对象
        PdfDictionary res = (PdfDictionary) PdfReader.getPdfObject(dictionary.get(PdfName.RESOURCES));
        //得到XOBJECT图片对象
        PdfDictionary xobj = (PdfDictionary) PdfReader.getPdfObject(res.get(PdfName.XOBJECT));
        if (xobj != null) {
            for (Iterator it = xobj.getKeys().iterator(); it.hasNext(); ) {
                PdfObject obj = xobj.get((PdfName) it.next());
                if (obj.isIndirect()) {
                    PdfDictionary tg = (PdfDictionary) PdfReader.getPdfObject(obj);
                    PdfName type = (PdfName) PdfReader.getPdfObject(tg.get(PdfName.SUBTYPE));
                    if (PdfName.IMAGE.equals(type)) {
                        PdfObject object = reader.getPdfObject(obj);
                        if (object.isStream()) {
                            PRStream prstream = (PRStream) object;
                            byte[] b;
                            try {
                                b = reader.getStreamBytes(prstream);
                            } catch (UnsupportedPdfException e) {
                                b = reader.getStreamBytesRaw(prstream);
                            }
                            FileOutputStream output = new FileOutputStream(String.format(imagePath + "outt%d.jpg", i));
                            output.write(b);
                            output.flush();
                            output.close();
                        }
                    }
                }
            }
        }
    }
}
